package bll

import (
	log "auth/collector/logger"
	"auth/errors"
	"auth/event"
	"auth/model"
	"auth/model/entity"
	"auth/store"
	"auth/store/postgres"
	"gorm.io/gorm"
	"time"
)

type authority struct {
	iAuthority     store.IAuthority
	iUserAuthority store.IUserAuthority
	iAuthorityMenu store.IAuthorityMenu
}

var Authority = &authority{}

func (a *authority) init() func() {
	a.iAuthority = postgres.Authority
	a.iUserAuthority = postgres.UserAuthority
	a.iAuthorityMenu = postgres.AuthorityMenu
	return func() {}
}

func (a *authority) onEvent(*event.Data) {}

func (a *authority) Create(in *model.AuthorityCreateRequest) error {
	var (
		err  error
		data *entity.Authority
	)
	if in.Type == nil {
		return errors.ParameterErr.Error()
	}
	if data, err = a.iAuthority.Find(in.AuthorityId); err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		log.Error(err)
		return err
	}
	if data.AuthorityId != 0 {
		return errors.RoleAlreadyExist.Error()
	}
	c := buildAuthority(in)
	_, err = a.iAuthority.Create(c)
	return err
}

func (a *authority) Update(in *model.AuthorityUpdateRequest) error {
	var (
		err  error
		data *entity.Authority
		dict = make(map[string]interface{})
	)
	if in.Type == nil {
		return errors.ParameterErr.Error()
	}
	if data, err = a.iAuthority.Find(in.AuthorityId); err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		log.Error(err)
		return err
	}
	if data.AuthorityId == 0 {
		return errors.RoleNotExist.Error()
	}
	dict["authority_name"] = in.AuthorityName
	dict["type"] = in.Type
	return a.iAuthority.Update(in.AuthorityId, dict)
}

func (a *authority) Delete(in *model.AuthorityDeleteRequest) error {
	data, err := a.iUserAuthority.FindByAuthorityId(in.AuthorityId)
	if err != nil && !errors.Is(gorm.ErrRecordNotFound, err) {
		log.Error("authority.Delete", err)
		return err
	}
	if len(data) != 0 {
		return errors.RoleUseProhibitDel.Error()
	}
	err = a.iUserAuthority.DeleteByAuthorityId(in.AuthorityId)
	err = a.iAuthorityMenu.DeleteByAuthorityId(in.AuthorityId)
	err = a.iAuthority.Delete(in.AuthorityId)
	return err
}

func (a *authority) List(in *model.AuthorityListRequest) (*model.AuthorityListResponse, error) {
	var (
		err   error
		total int
		list  []*entity.Authority
		out   = &model.AuthorityListResponse{}
	)

	if total, list, err = a.iAuthority.List(in); err != nil {
		return nil, err
	}

	out.Total = total
	out.Data = model.AuthoritysEntityToDto(list)

	return out, err
}

func buildAuthority(in *model.AuthorityCreateRequest) *entity.Authority {
	return &entity.Authority{

		AuthorityId: in.AuthorityId,

		AuthorityName: in.AuthorityName,

		ParentId: in.ParentId,

		Type: *in.Type,

		DefaultRouter: "",

		CreatedAt: time.Now().Unix(),

		UpdatedAt: time.Now().Unix(),
	}
}
